package com.feib.soeasy.dao.hibernate;

import java.io.Serializable;
import java.util.Date;

import org.hibernate.EmptyInterceptor;
import org.hibernate.Transaction;
import org.hibernate.type.Type;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.feib.soeasy.model.Auditable;
import com.feib.soeasy.util.UserUtil;

/**
 * @title (#)AuditInterceptor.java<br>
 * @description 紀錄異動時間的Hibernate Interceptor<br>
 * @author Jimmy Liu<br>
 * @version 1.0.0 2010/11/25
 * @copyright Far Eastern International Bank Copyright (c) 2010<br>
 * @20101025 create by Jimmy Liu<br>
 */
public class AuditInterceptor extends EmptyInterceptor {

    protected Logger logger = LoggerFactory.getLogger(this.getClass());

    private static final long serialVersionUID = -3562572881791100689L;

    private int updates;

    private int creates;

    private int loads;

    public boolean onFlushDirty(Object entity, Serializable id,
                    Object[] currentState, Object[] previousState,
                    String[] propertyNames, Type[] types) {
        logger.trace("Enter AuditInterceptor onFlushDirty method.");

        if (entity instanceof Auditable) {

            String userName = "SYSTEM_USER";
            
            if (null != UserUtil.getUser())
            {
                userName = UserUtil.getUserGroup().getGroupNo() + "_" + UserUtil.getUserId();
            }            

            updates++;

            boolean returnValue = false;

            for (int i = 0; i < propertyNames.length; i++) {
                if ("updatedDate".equals(propertyNames[i])) {
                    currentState[i] = new Date();
                    if (!returnValue)
                        returnValue = true;
                }

                if ("updatedBy".equals(propertyNames[i])) {
                    currentState[i] = userName;
                    if (!returnValue)
                        returnValue = true;
                }
            }

            return returnValue;

        }

        return false;

    }

    public boolean onLoad(Object entity, Serializable id, Object[] state,
                    String[] propertyNames, Type[] types) {
        logger.trace("Enter AuditInterceptor onLoad method.");

        if (entity instanceof Auditable) {
            loads++;
        }

        return false;

    }

    public boolean onSave(Object entity, Serializable id, Object[] state,
                    String[] propertyNames, Type[] types) {
        logger.trace("Enter AuditInterceptor onSave method.");

        if (entity instanceof Auditable) {

            String userName = "SYSTEM_USER";
            
            if (null != UserUtil.getUser())
            {
                userName = UserUtil.getUserGroup().getGroupNo() + "_" + UserUtil.getUserId();
            }

            creates++;

            boolean returnValue = false;

            for (int i = 0; i < propertyNames.length; i++) {
                if ("createdDate".equals(propertyNames[i]) || "updatedDate".equals(propertyNames[i])) {
                    state[i] = new Date();
                    if (!returnValue)
                        returnValue = true;
                }

                if ("createdBy".equals(propertyNames[i]) || "updatedBy".equals(propertyNames[i])) {
                    state[i] = userName;
                    if (!returnValue)
                        returnValue = true;
                }

            }

            return returnValue;

        }

        return false;

    }

    public void afterTransactionCompletion(Transaction tx) {
        logger.trace("Enter AuditInterceptor afterTransactionCompletion method.");

        if (tx.wasCommitted()) {

            logger.trace("Creations: " + creates + ", Updates: "
                            + updates + ", Loads: " + loads);

        }

        updates = 0;

        creates = 0;

        loads = 0;

    }

}
